﻿using Microsoft.Web.WebView2.Core;
using System;
using System.Text.Json;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls; // 需要为 Grid 引用
using System.Windows.Input;
using System.Windows.Threading;

namespace WebViewClient
{
    public partial class MainWindow : Window
    {
        private DispatcherTimer _gcTimer;
        private bool _isWebViewRestarting = false;

        public MainWindow()
        {
            InitializeComponent();
            // 重要：请确保您的 XAML 文件中，包含 webView 控件的那个 Grid 有一个名字，例如:
            // <Grid x:Name="MainGrid" Margin="10"> ... </Grid>
        }

        private async void Window_Loaded(object sender, RoutedEventArgs e)
        {
            // 程序启动时，调用我们自己的工厂方法来创建和初始化 WebView
            await CreateAndInitializeWebViewAsync();
            SetupGCTimer();
        }


        // 方法2：阻止右键事件冒泡
        private void WebView_PreviewMouseDown(object sender, MouseButtonEventArgs e)
        {
            if (e.RightButton == MouseButtonState.Pressed)
            {
                e.Handled = true; // 阻止右键菜单显示
            }
        }

        // =========================================================================
        // ▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼
        //
        //          这就是我们为了代码重用而创建的自定义辅助方法
        //
        // ▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲
        // =========================================================================
        /// <summary>
        /// 创建、初始化并配置一个新的 WebView2 实例。
        /// 这个方法是可重用的，用于程序启动和进程恢复。
        /// </summary>
        private async Task CreateAndInitializeWebViewAsync(string initialUrl = null)
        {
            try
            {
                StatusText.Text = "WebView2 环境初始化中...";
                var options = new CoreWebView2EnvironmentOptions { AdditionalBrowserArguments = "--disable-gpu --disable-gpu-compositing " };
                // 添加禁用开发者工具的参数
                options.AdditionalBrowserArguments =
                    "--disable-gpu " +
                    "--disable-web-security " +
                    "--disable-features=msWebOOUI,msPdfOOUI,msSmartScreenProtection " +
                    "--disable-dev-tools " +  // 禁用开发者工具
                    "--disable-extensions " +  // 禁用扩展
                    "--disable-plugins " +     // 禁用插件
                    "--no-sandbox ";           // 禁用沙箱（某些情况下需要）

                string cacheFolder = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "WebViewClient_Cache");
                var env = await CoreWebView2Environment.CreateAsync(null, cacheFolder, options);

                // 确保在UI线程上操作
                await Dispatcher.InvokeAsync(async () =>
                {
                    // 将环境和控件关联起来
                    await webView.EnsureCoreWebView2Async(env);

                    // 绑定所有事件
                    SubscribeToWebViewEvents();

                    // 注入C#对象
                    webView.CoreWebView2.AddHostObjectToScript("nativeHost", new HostObjectClass(this));

                    webView.ZoomFactor = 0.8;
                    //webView.ContextMenu = null;
                    StatusText.Text = "WebView2 初始化完成。";

                    // 导航到指定页面
                    webView.CoreWebView2.Navigate(initialUrl ?? UrlText.Text);
                });
            }
            catch (Exception ex)
            {
                MessageBox.Show($"WebView2 初始化失败: {ex.Message}", "严重错误", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }

        /// <summary>
        /// 统一管理WebView2事件订阅
        /// </summary>
        private void SubscribeToWebViewEvents()
        {
            if (webView?.CoreWebView2 == null) return;
            webView.CoreWebView2.ProcessFailed += CoreWebView2_ProcessFailed;
            webView.CoreWebView2.NavigationStarting += (s, e) => Dispatcher.Invoke(() => StatusText.Text = "导航开始...");
            webView.CoreWebView2.NavigationCompleted += (s, e) => Dispatcher.Invoke(() => StatusText.Text = "导航完成。");
            webView.CoreWebView2.WebMessageReceived += CoreWebView2_WebMessageReceived;
        }

        #region UI 事件处理器

        // 方法2：正则表达式（更严格）
        public static bool IsValidHttpUrlRegex(string url)
        {
            if (string.IsNullOrWhiteSpace(url))
                return false;
            return url.StartsWith("http://") || url.StartsWith("https://");
            //string pattern = @"^(http|https)://([\w-]+\.)+[\w-]+(/[\w- ./?%&=]*)?$";
            //return System.Text.RegularExpressions.Regex.IsMatch(url, pattern, System.Text.RegularExpressions.RegexOptions.IgnoreCase);
        }

        private void GoButton_Click(object sender, RoutedEventArgs e)
        {
            if (!IsValidHttpUrlRegex(UrlText.Text)) return;
            if (webView?.CoreWebView2 != null) webView.CoreWebView2.Navigate(UrlText.Text);
        }
        private void ReloadButton_Click(object sender, RoutedEventArgs e)
        {
            if (webView?.CoreWebView2 != null) webView.CoreWebView2.Reload();
        }
        private async void CallJsButton_Click(object sender, RoutedEventArgs e)
        {
            if (webView?.CoreWebView2 != null)
            {
                string resultJson = await webView.CoreWebView2.ExecuteScriptAsync("document.title");
                MessageBox.Show($"页面标题是: {JsonSerializer.Deserialize<string>(resultJson)}");
            }
        }
        private async void SetLocalStorageButton_Click(object sender, RoutedEventArgs e)
        {
            if (webView?.CoreWebView2 != null)
            {
                string script = $"localStorage.setItem('myWpfAppKey', 'Hello from WPF at {DateTime.Now}'); alert('LocalStorage已设置!');";
                await webView.CoreWebView2.ExecuteScriptAsync(script);
            }
        }
        private void InjectObjectButton_Click(object sender, RoutedEventArgs e)
        {
            if (webView?.CoreWebView2 != null)
            {
                string htmlContent = @"
                    <!DOCTYPE html><html><head><title>Host Object Test</title></head><body>
                    <h1>C# Host Object & Web Message Test</h1>
                    <button onclick='callNativeHost()'>调用C#方法 (Host Object)</button>
                    <button onclick='postMessageToHost()'>发送消息给C# (Web Message)</button>
                    <p>C#返回的消息: <b id='result'></b></p>
                    <script>
                        async function callNativeHost() {
                            const message = await window.chrome.webview.hostObjects.nativeHost.ShowMessage('你好，C#! 我是JS。');
                            document.getElementById('result').innerText = 'C#方法返回: ' + message;
                        }
                        function postMessageToHost() {
                            window.chrome.webview.postMessage({ type: 'greeting', content: '你好，我是来自网页的消息！' });
                        }
                    </script></body></html>";
                webView.CoreWebView2.NavigateToString(htmlContent);
            }
        }
        private void DevToolsButton_Click(object sender, RoutedEventArgs e)
        {
            webView?.CoreWebView2?.OpenDevToolsWindow();
        }

        private async void ScriptButton_Click(object sender, RoutedEventArgs e)
        {
            if(null != ScriptText.Text)
            {
                await webView.CoreWebView2.ExecuteScriptAsync(ScriptText.Text);
            }
        }

        #endregion

        #region 健壮性与核心逻辑

        private void CoreWebView2_WebMessageReceived(object sender, CoreWebView2WebMessageReceivedEventArgs e)
        {
            string jsonMessage = e.WebMessageAsJson;
            if (!string.IsNullOrEmpty(jsonMessage))
            {
                Dispatcher.Invoke(() =>
                {
                    StatusText.Text = $"收到JS消息: {jsonMessage}";
                    MessageBox.Show(this, $"收到来自网页的JSON消息:\n{jsonMessage}", "WebMessage");
                });
            }
        }

        private async void CoreWebView2_ProcessFailed(object sender, CoreWebView2ProcessFailedEventArgs e)
        {
            if (_isWebViewRestarting) return;
            _isWebViewRestarting = true;
            MessageBox.Show(this, "WebView2 进程意外终止！正在尝试恢复...", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
            string currentUrl = webView.Source?.ToString() ?? UrlText.Text;

            await Dispatcher.InvokeAsync(async () =>
            {
                try
                {
                    MainGrid.Children.Remove(webView);
                    webView.Dispose();

                    webView = new Microsoft.Web.WebView2.Wpf.WebView2();
                    webView.Margin = new Thickness(0, 5, 0, 0);
                    Grid.SetRow(webView, 1);
                    MainGrid.Children.Add(webView);

                    // 在这里，我们再次调用了我们的辅助方法来重建 WebView
                    await CreateAndInitializeWebViewAsync(currentUrl);
                    MessageBox.Show(this, "WebView2 已成功恢复。", "成功", MessageBoxButton.OK, MessageBoxImage.Information);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(this, $"WebView2 恢复失败: {ex.Message}\n应用可能需要重启。", "严重错误", MessageBoxButton.OK, MessageBoxImage.Error);
                }
                finally
                {
                    _isWebViewRestarting = false;
                }
            });
        }
        #endregion

        #region 内存与清理
        private void SetupGCTimer()
        {
            _gcTimer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(30) };
            _gcTimer.Tick += async (s, e) =>
            {
                GC.Collect();
                GC.WaitForPendingFinalizers();
                if (webView?.CoreWebView2 != null)
                {
                    await webView.CoreWebView2.CallDevToolsProtocolMethodAsync("HeapProfiler.collectGarbage", "{}");
                }
            };
            _gcTimer.Start();
        }

        protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
        {
            _gcTimer?.Stop();
            webView?.Dispose();
            base.OnClosing(e);
        }
        #endregion
    }

    public class HostObjectClass
    {
        private MainWindow _mainWindow;
        public HostObjectClass(MainWindow window) { _mainWindow = window; }
        public string ShowMessage(string message)
        {
            string response = $"C# 收到了你的消息: '{message}'";
            _mainWindow.Dispatcher.Invoke(() => MessageBox.Show(_mainWindow, message, "来自JS的调用"));
            return response;
        }
        public string AppVersion => "1.0.0";
    }
}